﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SpectrumClient
{
    public class SocketCient
    {
        private static readonly SocketCient instance = new SocketCient();

        private object _lock = new object();

        /// <summary>
        /// 私有构造函数，防止实例化
        /// </summary>
        private SocketCient()
        {
            lock (_lock)
            {
                ServerConnect();
            }
        }

        /// <summary>
        ///  公共静态方法，返回唯一的实例
        /// </summary>
        public static SocketCient Instance => instance;

        /// <summary>
        /// 消息回调
        /// </summary>
        public Action<string> MsgCallback = (a) =>
        {
            try
            {
                File.AppendAllText("C:\\AutoControlSpectrum\\log.txt", $"【{DateTime.Now:MM-dd HH:mm:ss}】{a}{Environment.NewLine}");
            }
            catch (Exception)
            {
            }
        };

        /// <summary>
        /// 缓存数据
        /// </summary>
        public string CacheData = string.Empty;

        /// <summary>
        /// 自动登录
        /// </summary>
        public bool CacheDataAutoLogin = true;

        /// <summary>
        /// 客户端
        /// </summary>
        private Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        /// <summary>
        /// 服务ip
        /// </summary>
        private string SocketIp = IPAddress.Loopback.ToString();// "100.96.143.46";

        /// <summary>
        /// 服务端口
        /// </summary>
        private int SocketPort = 776;

        internal static object Instanc;

        /// <summary>
        /// 连接服务
        /// </summary>
        private void ServerConnect()
        {
            Exit();

            Task.Run(async () =>
            {
                await Task.Delay(500);
                LoopConnect();
                _ = Task.Run(ReceiveLoop);
            });
        }

        /// <summary>
        /// 连接服务
        /// </summary>
        public void LoopConnect()
        {
            int attempts = 0;
            try
            {
                while (!clientSocket.Connected)
                {
                    try
                    {
                        attempts++;
                        Console.WriteLine();
                        clientSocket.Connect(SocketIp, SocketPort);
                    }
                    catch (SocketException)
                    {
                        MsgCallback($"连接失败次数： " + attempts);
                        Task.Delay(1000).Wait();
                        Console.Clear();
                    }
                }
            }
            catch (Exception ex)
            {
                MsgCallback($"连接错误 SocketIp：{SocketIp}, SocketPort：{SocketPort}，原因：{ex.Message}");
            }
            MsgCallback($"连接成功 SocketIp：{SocketIp}, SocketPort：{SocketPort}");
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="eventName">事件标题</param>
        /// <param name="data">数据</param>
        public void SendLoop(string eventName, string data)
        {
            try
            {
                string txt = string.Format("{0}(:){1}", eventName, data);
                byte[] buffer = Encoding.UTF8.GetBytes(txt);
                clientSocket?.Send(buffer);
            }
            catch (Exception ex)
            {
                LoopConnect();
            }
        }

        /// <summary>
        /// 发送样品结果
        /// </summary>
        /// <param name="data"></param>
        public void SendSampleCalculateResult(string data)
        {
            SendLoop("SampleCalculateResult", data);
        }

        /// <summary>
        /// 接收消息
        /// </summary>
        public void ReceiveLoop()
        {
            while (true)
            {
                byte[] receivedBuf = new byte[2048];
                int rec = clientSocket.Receive(receivedBuf);
                byte[] data = new byte[rec];
                Array.Copy(receivedBuf, data, rec);
                string resultStr = Encoding.UTF8.GetString(data);
                MsgCallback($"接收到: " + resultStr);

                var cells = resultStr.Split(new string[] { "(:)" }, StringSplitOptions.RemoveEmptyEntries).ToList();
                var type = cells.First();
                var value = cells.Last();

                switch (type)
                {
                    case "DeviceScanBackground":
                        EventBus.ScanBackgroundEvent();
                        break;

                    case "DeviceScanStart":
                        EventBus.ScanStartEvent();
                        break;

                    case "SampleSelectSample":
                        EventBus.SampleSelectEvent();
                        break;

                    case "SampleCalculateSample":
                        EventBus.SampleCalculateEvent(value);
                        break;

                    case "SampleCalculateResult":
                        EventBus.SampleCalculateResultEvent();
                        // string txt = "样品名称=Administrator 132;说明=样品 132 用户名称 Administrator 日期 周五 2024年7月26日;Oppma=4.69089;Cppma=2.65755";
                        // SendSampleCalculateResult(txt);
                        break;

                    case "DeleteTreeNode":
                        EventBus.DeleteTreeNodeEvent();
                        break;

                    default:
                        break;
                }
            }
        }

        public void Exit()
        {
            if (clientSocket.Connected)
            {
                clientSocket?.Shutdown(SocketShutdown.Both);
                clientSocket?.Close();
            }
        }
    }

    /// <summary>
    /// 事件集合
    /// </summary>
    public class EventBus
    {
        /// <summary>
        /// 扫描背景
        /// </summary>
        public static Action ScanBackgroundEvent = () => { };

        /// <summary>
        /// 扫描开始
        /// </summary>
        public static Action ScanStartEvent = () => { };

        /// <summary>
        /// 样品选择事件
        /// </summary>
        public static Action SampleSelectEvent = () => { };

        /// <summary>
        /// 样品计算
        /// </summary>
        public static Action<string> SampleCalculateEvent = (string macroId) => { };

        /// <summary>
        /// 样品计算结果
        /// </summary>
        public static Action SampleCalculateResultEvent = () => { };

        /// <summary>
        /// 删除历史样品
        /// </summary>
        public static Action DeleteTreeNodeEvent = () => { };
    }
}